/* 
 * File:   Context.h
 * Author: Gab'z
 *
 * Created on 25 mai 2012, 13:56
 */

#ifndef CONTEXT_H
#define	CONTEXT_H

#include <string>
#include <list>
#include "parameters/Parameters.h"
#include "command/literal/StackList.h"
#include "memento/MementoCaretaker.h"
#include "command/CommandMap.h"
#include "../exception/ContextException.h"
#include "../log/LogSystem.h"

namespace calculator {
    const std::string saveFilename = "calculatrice.xml";

    /**
     * Classe de base du modèle dans le schéma MVC.
     * Le contexte contient :
     * - la saisie courante
     * - le gestionnaire de Memento
     * - les paramètres @see Parameters
     * - les piles @see StackList, Stack
     * - la liste de commandes @see CommandMap
     */
    class Context {
    public:

        /**
         * Singleton Context.
         * @return crée et/ou renvoie l'unique instance de Context.
         * Initialise la ligne de saisie à vide et le statut _error du contexte à false
         * Met en place les Parameters, la liste de commandes,
         *  le conteneur de Memento et initialise une StackList
         *  avec une Stack vide
         */
        static Context* getInstance() {
            if (instance == 0) {
                instance = new Context();
            }
            return instance;
        }

        /**
         * Singleton Context.
         * Détruit l'unique instance de Context.
         * Libère la mémoire utilisée par :
         * - le conteneur de Memento
         * - la liste de piles @see StackList
         * - la liste de commandes @see CommandMap
         * - les paramètres @see Parameters
         */
        static void deleteInstance() {
            if (instance != 0) delete instance;
        }
       
        // <editor-fold defaultstate="collapsed" desc="GETTER/SETTER">

        void setInputString(const std::string& str) {
            _inputString = str;
        }

        std::string getInputString() const {
            return _inputString;
        }

        Parameters* getParameters() const {
            return _parameters;
        }

        void setParameters(const Parameters* parameters) {
            log->debug("setParameters");
            *_parameters = *parameters;
        }

        MementoCaretaker* getMementoCaretaker() const {
            return _mementoCaretaker;
        }

        CommandMap* getCommandMap() const {
            return _commandMap;
        }

        Stack* getCurrentStack() const {
            return _stackList->getCurrentStack();
        }

        void setCurrentStack(const unsigned int i) throw (ContextException) {
            try {
                _stackList->setCurrentStack(i);
            } catch (ContextException& e) {
                throw;
            }
        }

        StackList* getStackList() const {
            return _stackList;
        }

        void setStackList(const StackList* stackList) {
            log->debug("setStackList");
            delete _stackList;
            _stackList = stackList->clone();
        }

        bool getError() const {
            return _error;
        }

        void setError(bool b = true) {
            _error = b;
        }// </editor-fold>

        /**
         * Sauvegarde du contexte directe.
         * Entorse au schéma MVC, le context est capable 
         * de s'enregistrer sans passer par le moteur.
         */
        void saveContextToXML() const;

    private:
        
        /**
         * instance du Singleton Context.
         */
        static Context* instance;

        /**
         * Ligne de saisie du contexte.
         * On ne travaille pas directement avec l'interface.
         */
        std::string _inputString;
        
        /**
         * Booléen mis à false au début de chaque exécution, 
         * mis à true si une erreur se produit pendant l'exécution 
         * d'une commande et lu ensuite par l'interface
         * A nouveau pour ne pas travailler directement avec l'interface
         */
        bool _error;

        /**
         * Pointeur vers les paramètres courants. @see Parameters
         */
        Parameters* _parameters;
        
        /**
         * Pointeur vers la liste de commandes de l'application. @see CommandMap
         */
        CommandMap* _commandMap;
        
        /**
         * Pointeur vers le conteneur de Memento. @see MementoCareTaker
         */
        MementoCaretaker* _mementoCaretaker;
        
        /**
         * Pointeur vers la StackList courante. @see Stack
         */
        StackList* _stackList;

        /**
         * Constructeur privé utilisé par le Singleton.
         */
        Context();

        /**
         * Destructeur privé utilisé par le Singleton.
         */
        virtual ~Context();
        
        static Logger* log;
    };
}

#endif	/* CONTEXT_H */

